package com.hong.utils.condition;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * @Auther: Administrator
 * @Date: 2018/7/23 17:42
 * @Description:生产者消费者模式
 */
public class ConditionExample3 {
    /**锁*/
    private final static ReentrantLock  lock = new ReentrantLock();
    /**生产者*/
    private final static Condition PRODUCE_COND = lock.newCondition();
    /**消费者*/
    private final static Condition CONSUME_COND = lock.newCondition();
    /**池子*/
    private final static LinkedList<Long> TIMESTAME_POOL = new LinkedList<>();
    /**最大值*/
    private final static int MAX_CAPACITY = 100;

    public static void main(String[] args) throws InterruptedException {
        IntStream.range(0,6).boxed().forEach(ConditionExample3::beginProduce);
        IntStream.range(0,13).boxed().forEach(ConditionExample3::beginComsume);

    }

    private static void beginProduce(int i){
        new Thread(()->{
            for (;;){
                produce();
                sleep(2);
            }
        },"P-"+i).start();
    }

    private static void beginComsume(int i){
        new Thread(()->{
            for (;;){
                consume();
                sleep(3);
            }
        },"C-"+i).start();
    }

    /**生产方法*/
    private static void produce(){
        try {
            lock.lock();
            while (TIMESTAME_POOL.size()>=MAX_CAPACITY){
                PRODUCE_COND.await();
            }
            System.out.println("PRODUCE_COND.getWaitQueueLength->"+lock.getWaitQueueLength(PRODUCE_COND));
            long value = System.currentTimeMillis();
            System.out.println(Thread.currentThread().getName()+" -P-"+ value);
            TIMESTAME_POOL.addLast(value);
            CONSUME_COND.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    private static void consume(){
        try {
            lock.lock();
            while (TIMESTAME_POOL.isEmpty()){
                CONSUME_COND.await();
            }
            System.out.println("CONSUME_COND.getWaitQueueLength->"+lock.getWaitQueueLength(CONSUME_COND));
            long value = System.currentTimeMillis();
            System.out.println(Thread.currentThread().getName()+" -P-"+ value);
            TIMESTAME_POOL.removeFirst();
            PRODUCE_COND.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    /**休眠*/
    private static void sleep(long sec){
        try {
            TimeUnit.SECONDS.sleep(sec);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
